﻿using System;
using System.IO;
using System.Diagnostics;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Configuration.Install;
using System.Linq;
using System.Windows.Forms;
using Microsoft.Win32;
using Shell32;

namespace SPVisualDevDeployCustomAction
{
    [RunInstaller(true)]
    public partial class InstallerClass : Installer
    {
        private SPVisualDevWinSvc.ProjectInstaller SPVDWinSvc;

        public InstallerClass()
        {
            InitializeComponent();
        }

        public override void Install(IDictionary stateSaver)
        {
            using (BackgroundWorker worker_install = new BackgroundWorker())
            {
                worker_install.DoWork += new DoWorkEventHandler(worker_install_DoWork);
                worker_install.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_install_RunWorkerCompleted);

                worker_install.RunWorkerAsync();


                using (FormInstallingTemplates form = new FormInstallingTemplates())
                {
                    form.Text = "Installing Visual Studio 2008 custom templates";
                    form.Show();
                    form.Activate();
                    form.BringToFront();

                    while (worker_install.IsBusy)
                    {
                        Application.DoEvents();
                    }
                }

            }

            base.Install(stateSaver);
        }


        private void worker_install_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
        }

        private void worker_install_DoWork(object sender, DoWorkEventArgs e)
        {
            string VSInstallDir = (string)Registry.GetValue("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\9.0", "InstallDir", string.Empty);
            string InstallPath = Path.GetDirectoryName(this.Context.Parameters["assemblypath"]);

            if (VSInstallDir.EndsWith("\\"))
                VSInstallDir = VSInstallDir.Substring(0, VSInstallDir.Length - 1);


            /*for backwards comp with windows server 2003 etc. */
            Type shellAppType = Type.GetTypeFromProgID("Shell.Application");
            IShellDispatch4 shell = Activator.CreateInstance(shellAppType) as IShellDispatch4;

            /*
            string wspbuilder = (string)Registry.GetValue("HKEY_LOCAL_MACHINE\\SOFTWARE\\SPVisualDev", "WSPBuilderPath", null);
            if (!string.IsNullOrEmpty(wspbuilder))
            {
                Folder zip = shell.NameSpace(InstallPath + "\\WSPBuilder.zip");
                Folder dest_folder = shell.NameSpace(InstallPath);
                dest_folder.CopyHere(zip.Items(), 20);
            }
            */

            /*
            try
            {
                string InstallationType = (string)Registry.GetValue("HKEY_LOCAL_MACHINE\\SOFTWARE\\SPVisualDev", "InstallationType", string.Empty);
                if (InstallationType != "2")
                    Copy12HiveFiles(InstallPath);
            }
            catch(Exception ex)
            {
                string msg = "Failed to install files into 12 hive. Info: " + ex.ToString();
                throw new Exception(msg);
//                MessageBox.Show(msg, "Error", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
            }
            */

            Folder templates = shell.NameSpace(InstallPath + "\\Templates\\ItemTemplates");
            Folder dir = shell.NameSpace(VSInstallDir + "\\ItemTemplates");
            dir.NewFolder("SPVisualDev", 0);

            dir = shell.NameSpace(VSInstallDir + "\\ItemTemplates\\SPVisualDev");
            dir.CopyHere(templates.Items(), 20);


            templates = shell.NameSpace(InstallPath + "\\Templates\\ProjectTemplates");
            dir = shell.NameSpace(VSInstallDir + "\\ProjectTemplates");
            dir.NewFolder("SPVisualDev", 0);

            dir = shell.NameSpace(VSInstallDir + "\\ProjectTemplates\\SPVisualDev");
            dir.CopyHere(templates.Items(), 20);


            ShellExecute(VSInstallDir + "\\devenv.exe", "/InstallVSTemplates", false);
        }

        protected override void OnAfterUninstall(IDictionary savedState)
        {
            UninstallAction(false);

            base.OnAfterUninstall(savedState);
        }

        private void worker_uninstall_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
        }

        private void worker_uninstall_DoWork(object sender, DoWorkEventArgs e)
        {
            try
            {
                bool isRollback = (bool)e.Argument;

                string VSInstallDir = (string)Registry.GetValue("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\9.0", "InstallDir", string.Empty);
                string InstallPath = Path.GetDirectoryName(this.Context.Parameters["assemblypath"]);

                if (VSInstallDir.EndsWith("\\"))
                    VSInstallDir = VSInstallDir.Substring(0, VSInstallDir.Length - 1);


                if (Directory.Exists(VSInstallDir + "\\ItemTemplates\\SPVisualDev"))
                    Directory.Delete(VSInstallDir + "\\ItemTemplates\\SPVisualDev", true);

                if (Directory.Exists(VSInstallDir + "\\ProjectTemplates\\SPVisualDev"))
                    Directory.Delete(VSInstallDir + "\\ProjectTemplates\\SPVisualDev", true);


                /*
                try
                {
                    string InstallationType = (string)Registry.GetValue("HKEY_LOCAL_MACHINE\\SOFTWARE\\SPVisualDev", "InstallationType", string.Empty);
                    if (InstallationType != "2")
                        Delete12HiveFiles(InstallPath);
                }
                catch
                {
                    MessageBox.Show("Failed to uninstall files from 12 hive. Uninstall will continue.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                }
                */


                ShellExecute(VSInstallDir + "\\devenv.exe", "/InstallVSTemplates", false);

                //if (!isRollback)
                //{
                    //Addin must be removed prior resetting addin configuration, otherwise it will load again :-)
                    try
                    {
                        File.Delete(InstallPath + "\\SPVisualDev_2008.AddIn");
                    }
                    catch{}

                    try
                    {
                        ShellExecute(VSInstallDir + "\\devenv.exe", "/ResetAddin \"SPVisualDev.Addin.Connect\" /Command Exit", false);
                    }
                    catch { }
                //}


            }
            catch (Exception ex)
            {
                MessageBox.Show("Some files could not be uninstalled. " + ex.ToString(), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        protected override void OnAfterRollback(IDictionary savedState)
        {
            UninstallAction(true);

            base.OnAfterRollback(savedState);
        }

        private void UninstallAction(bool isRollback)
        {
            using (BackgroundWorker worker_uninstall = new BackgroundWorker())
            {
                worker_uninstall.DoWork += new DoWorkEventHandler(worker_uninstall_DoWork);
                worker_uninstall.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_uninstall_RunWorkerCompleted);

                worker_uninstall.RunWorkerAsync(isRollback);

                using (FormInstallingTemplates form = new FormInstallingTemplates())
                {
                    form.Text = "Uninstalling Visual Studio 2008 custom templates";
                    form.Show();
                    form.Activate();
                    form.BringToFront();

                    while (worker_uninstall.IsBusy)
                    {
                        Application.DoEvents();
                    }

                }


            }

        }

        private void ShellExecute(string ExecutablePath, string Arguments, bool Visible)
        {
            using (Process p = new Process())
            {
                p.StartInfo.FileName = ExecutablePath;
                p.StartInfo.Arguments = Arguments;
                p.StartInfo.WindowStyle = Visible ? ProcessWindowStyle.Normal : ProcessWindowStyle.Hidden;

                p.Start();
                p.WaitForExit();

                if (p.ExitCode != 0)
                    throw new Exception(p.ExitCode.ToString());
            }
        }

        private void Copy12HiveFiles(string InstallDir)
        {
            CopyOneFolder(InstallDir + "\\12HiveFiles", GetSharePointInstallPath());
        }
        private void CopyOneFolder(string SourceDir,string DestinationDir)
        {
            if (!Directory.Exists(DestinationDir))
                Directory.CreateDirectory(DestinationDir);

            foreach (string file in Directory.GetFiles(SourceDir))
            {
                File.Copy(file, DestinationDir + "\\" + Path.GetFileName(file), true);
            }

            foreach (string dir in Directory.GetDirectories(SourceDir))
            {
                DirectoryInfo info = new DirectoryInfo(dir);

                CopyOneFolder(dir, DestinationDir + "\\" + info.Name);
            }

        }

        private void Delete12HiveFiles(string InstallDir)
        {
            DeleteOneFolder(InstallDir + "\\12HiveFiles", GetSharePointInstallPath());
        }
        private void DeleteOneFolder(string SourceDir, string DestinationDir)
        {
            if (!Directory.Exists(DestinationDir) || !Directory.Exists(SourceDir))
                return;

            foreach (string file in Directory.GetFiles(SourceDir))
            {
                try
                {
                    File.Delete(DestinationDir + "\\" + Path.GetFileName(file));
                }
                catch { }
            }

            foreach (string dir in Directory.GetDirectories(SourceDir))
            {
                try
                {
                    DirectoryInfo info = new DirectoryInfo(dir);

                    DeleteOneFolder(dir, DestinationDir + "\\" + info.Name);
                }
                catch { }
            }

        }

        private string GetSharePointInstallPath()
        {
            string path = null;

            //Try by getting path by looking in the registry.
            try
            {
                path = (string)Registry.GetValue("HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Shared Tools\\Web Server Extensions\\12.0", "Location", "");
            }
            catch { }


            //Still no value? Try environment variables.
            try
            {
                if (string.IsNullOrEmpty(path))
                {
                    string probe_path = @"\Microsoft Shared\web server extensions\12\BIN\STSADM.exe";
                    path = Environment.GetFolderPath(Environment.SpecialFolder.CommonProgramFiles) + probe_path;
                    if (string.IsNullOrEmpty(path) || !File.Exists(path))
                        path = Environment.GetEnvironmentVariable("CommonProgramW6432") + @"\Microsoft Shared\web server extensions\12";
                    else
                        path = Environment.GetFolderPath(Environment.SpecialFolder.CommonProgramFiles) + @"\Microsoft Shared\web server extensions\12";
                }
            }
            catch { }

            //If the directory is not valid, throw an error.
            if (!Directory.Exists(path))
                throw new Exception("Can not find SharePoint 12 hive on system.");

            if (!string.IsNullOrEmpty(path))
                if (path.EndsWith("\\"))
                    path = path.Substring(0, path.Length - 1);

            return path;
        }

    }
}
